import type { ModalFuncProps } from "antd"
import { Modal, message } from "antd"
import dayjs from "dayjs"
import _ from "lodash"
import { DebounceSettings, isFunction } from "lodash-es"
import { Dispatch, MutableRefObject, SetStateAction, useEffect, useMemo, useRef, useState } from "react"

//将Ttree
export function TreeToArray(tree: any) {
  // 判断 tree 是否有值，无返回 []
  if (!Array.isArray(tree) || !tree.length) return []
  let res: any = []
  tree.forEach((v) => {
    // tree的每个元素都 放入到 res里面
    res.push(v)
    if (v.children) {
      // 有children 就把 children数据递归 返回  依次放到 res里面
      res.push(...TreeToArray(v.children))
    }
  })
  return res
}

//校验手机号格式
export function IsPhoneFormat(phone: string) {
  var str = "手机号码"
  var myreg = /^[1][3,4,5,7,8,9][0-9]{9}$/
  return myreg.test(phone)
}

// 时间格式化
export const timeFormatter = (
  time: string,
  format: string = "YYYY-MM-DD HH:mm"
) => {
  if (!time) return ""
  return dayjs(time).format(format)
}

/** 绑定触发到底部的滚动事件 */
export function useScrollBottom(dom: HTMLDivElement | null, cb: () => any) {
  // 记录上一次的回调
  const ref = useRef<any>(() => null)
  // 绑定事件
  useEffect(() => {
    dom?.removeEventListener("scroll", ref.current)
    dom?.addEventListener("scroll", scrollCb)
    ref.current = scrollCb
  }, [dom, cb])
  // 实际的回调
  const scrollCb = useMemo(() => {
    let oldScrollTop = 0
    return throttle((e: Event) => {
      const { target } = e
      if (!target) return
      const { clientHeight, scrollTop, scrollHeight } = target
      if (scrollTop === oldScrollTop) {
        return
      } else {
        // 向上滚动
        if (oldScrollTop > scrollTop) {
          oldScrollTop = scrollTop
          return
        }
        oldScrollTop = scrollTop
      }
      if (clientHeight + scrollTop + 50 > scrollHeight) {
        // 加载更多
        cb()
      }
    }, 100)
  }, [dom, cb])

  return []
}

export const emptyFn = () => undefined
export interface anyObj {
  [p: string]: any
}
/** 从对象数组中，找到属性key相等的元素，可用children嵌套 */
export const findObjByKey = <T extends anyObj>(
  arr: T[],
  val: string | number,
  key = "id",
  children = "children"
): T | undefined => {
  if (val === void 0) {
    return void 0
  }
  const stack = arr.slice(0)
  while (stack.length) {
    const last = stack.pop()
    if (last?.[key] === val) {
      return last
    }
    const childrenArr = last?.[children]
    if (childrenArr?.length) {
      stack.push(...childrenArr)
    }
  }
  return undefined
}
/** 调用 Modal.confirm，用于删除的对话框 */
export function likeNormalModal(props: ModalFuncProps) {
  const { className = "", ...rest } = props
  Modal.confirm({
    cancelText: "取消",
    okText: "确定",
    className: "like_normal_modal " + className,
    title: "提示",
    icon: null,
    centered: true,
    content: "确定要删除吗？",
    ...rest,
  })
}
/** 调用 Modal.confirm 模拟一个蒙层 */
export function Mantle() {
  return Modal.confirm({
    title: null,
    icon: null,
    maskStyle: { backgroundColor: "transparent" },
    zIndex: 99999,
    bodyStyle: {
      display: "none",
    },
  })
}

/**
 * 将tree结构数组,根据children,转换为没有层级的数组
 * 用法： const OneArr =  flatObjArr(arr)
 */
export function flatObjArr<Type extends anyObj>(
  oldArr: Type[],
  children = "children",
  resArr: Type[] = []
) {
  oldArr?.forEach((val) => {
    resArr.push(val)
    if (val?.[children]?.length) {
      flatObjArr(val?.[children], children, resArr)
    }
  })

  return resArr
}

export const dateTimeFormat = "YYYY-MM-DD"

// 获取序号
export const getIndex = (index: number, page: any) => {
  const { current, pageSize } = page
  const i = (current - 1) * pageSize + index + 1
  // return `${i}`?.padStart(2, "0")
  return i
}

// 第一次不执行
export const useUpdateEffect = (fn: Function, inputs: any[]) => {
  const didMountRef = useRef(false)
  useEffect(() => {
    if (didMountRef.current) fn()
    else didMountRef.current = true
  }, inputs)
}

// 获取页面权限
export const getPagePermission = async (
  path: string,
  menuList: any[] | null,
  setPagePower: any
): Promise<{ editpower: boolean; seekpower: boolean }> => {
  const menuid = getMenuId(path, menuList)
  const { data }: { data: { editpower: boolean; seekpower: boolean } } =
    await window.axiosGet("1500167", { menuid })
  // const { seekpower, editpower } = data;
  setPagePower({ ...data })
  return data
}

const getMenuId = (path: string, menuList: any[] | null) => {
  let id
  const v = (list: any[]) => {
    list.map((item: any) => {
      if (item.cdjz === path) {
        id = item.id
      } else if (item?.children?.length) {
        v(item.children)
      }
    })
  }
  v(menuList || [])
  return id
}

// 导出文件
export const importDocument = async (
  url: string,
  type: string,
  docName: string,
  params: any,
  loadingMsg?: string
) => {
  // const mantle = Mantle();
  message.loading({
    content: loadingMsg || "正在导出文件",
    key: "DownDocument",
    duration: 0,
  })
  const res = await window.axiosGet(url, params, undefined, {
    responseType: "blob",
  })
  const blob = new Blob([res], { type: `application/${type}` }) //指定打印文件类型pdf
  const href = window.URL.createObjectURL(blob) // 创建下载的链接
  const link = document.createElement("a") //创建a标签
  link.style.display = "none"
  link.target = "downloadFile"
  link.href = href // 设置a标签路径
  link.download = docName //设置文件名
  document.body.appendChild(link)
  link.click()
  URL.revokeObjectURL(link.href) // 释放 URL对象
  document.body.removeChild(link)
  message.success("导出成功")
  message.destroy("DownDocument")
  // mantle.destroy();
}

/** 生成 UUID */
export function randomUUID() {
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0,
      v = c == "x" ? r : (r & 0x3) | 0x8
    return v.toString(16)
  })
}

/**
 * 修改嵌套数组数据
 * @param {Array} data 数据数组
 * @param  setData 修改数据的set方法
 * @param  record 当前修改行的数据
 * @param {string} field 当前修改的字段名
 * @param {*} newVal 新值
 * @param {string} rowKey 根据哪个字段来找当前行 一般和表格rowkey一样
 * @param {boolean} update 是否立即调用setData更新(一次需要修改多个数据时可以传false 在最后一个修改时再更新)
 * @returns 返回修改后的新数组
 */
export const onArrayDataChange = (
  data: any[],
  setData: any,
  record: any,
  field: string,
  newVal: any,
  rowKey = "tid",
  update = true
) => {
  const rowChange: any = (list: any[]) => {
    return list.map((item: any) => {
      // if (!item.children?.length && item[rowKey] === record[rowKey])
      if (item[rowKey] === record[rowKey]) {
        return {
          ...item,
          [field]: newVal,
          row_edited: 1, // 添加标识表示该行编辑过
        }
      } else if (item.children?.length) {
        return {
          ...item,
          children: rowChange(item.children),
        }
      }
      return item
    })
  }
  const newData = rowChange(data)
  if (update) setData([...newData])
  return newData
}

/**
 * 修改嵌套数组数据
 * @param {Array} data 数据数组
 * @param {string} field 当前修改的字段名
 * @param {*} newVal 新值
 * @param {string} nowRoKey 当前的key值（对应rowKey的值）
 * @param {string} rowKey 根据哪个字段来找当前行
 * @returns 返回修改后的新数组
 */
export const onArrayDataChange1 = (
  data: any[],
  field: string,
  newVal: any,
  nowRoKey: string,
  rowKey = "tid",
) => {
  const rowChange: any = (list: any[]) => {
    return list.map((item: any) => {
      if (item[rowKey] === nowRoKey) {
        return {
          ...item,
          [field]: newVal,
          row_edited: 1, // 添加标识表示该行编辑过
        }
      } else if (item.children?.length) {
        return {
          ...item,
          children: rowChange(item.children),
        }
      }
      return item
    })
  }
  const newData = rowChange(data)
  return newData
}

/**
 * 获取嵌套数组的某一项值 返回的是一个数组 例如所有 tid 也可以传一个条件进行筛选
 * @param data
 * @param field 要返回的字段
 * @param predicate 筛选条件
 */
export const getArrayValues = (
  data: readonly any[],
  field: string = "tid",
  predicate?: (record: any) => boolean
) => {
  const list: any[] = []
  const v = (arr: any[]) => {
    arr.forEach((item: any) => {
      if (predicate) {
        if (predicate(item)) list.push(item[field])
      } else {
        list.push(item[field])
      }
      if (item.children?.length) v(item.children)
    })
  }
  v(data)
  return list
}

// 根据属性值找到某一行的数据
export const getRowByField = (
  list: readonly any[],
  value: any,
  filed: string = "tid"
) => {
  let record
  const v = (arr: any[]) => {
    arr.forEach((item: any, index: number) => {
      if (item[filed] === value) return (record = { ...item })
      if (item.children?.length) v(item.children)
    })
  }
  v(list)
  return record
}

// export const priceFormatter = (price: string | number) => {
//   const priceNum = Number(price).toFixed(0);
//   return priceNum.toString().replace(/\B(?=(\d{3})+$)/g, ",");
// };

// 数字千分位
export const getNumThousandth = (num: number | string) => {
  if (!num) return 0
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}

/**
 * 价格格式化
 * @param {any} val 价格(单位是元的)
 * @param {'元'|'万元'} unit  true为元，不是万元
 * @param {boolean} thousandSplit 显示为千分位
 * @param {number|string} placeholder 没有值时默认显示内容
 */
export const priceFormatter = (
  val: number,
  unit: "元" | "万元" = "元",
  placeholder: number | string = "",
  thousandSplit: boolean = true
) => {
  if (val === null || val === undefined) return placeholder
  // if (val===0) return 0
  let price: string | number = Number(val)
  if (typeof price !== "number") return price
  if (unit === "万元") {
    price = (price / 10000).toFixed(2)
  } else {
    price = price.toFixed(2)
  }
  if (thousandSplit) return getNumThousandth(price)
  return price
}

/**
 * 简单判断是否为数字
 * @param value
 * @returns
 */
export const isNumberVal = (value: any) => {
  return !isNaN(+value)
}

/**
 * 处理js数字计算 有小数点可能出现的问题
 * @param {number} num1 运算符左侧
 * @param {number} num2 运算符右侧
 * @param {'+ - * 除'} symbol 运算符
 * @param {number} fixLen 可选， toFixed的参数 (有误的时候，返回 '')
 */
export const amend = (
  num1: number,
  num2: number,
  symbol: any,
  fixLen: number
) => {
  if (
    !isNumberVal(+num1) ||
    !isNumberVal(+num2) ||
    num1 === null ||
    num2 === null
  ) {
    return ""
  }
  if (symbol === "/" && num2 == 0) {
    return ""
  }
  var str1 = num1.toString(),
    str2 = num2.toString(),
    str1Length,
    str2Length
  let result = 0
  //解决整数没有小数点方法
  try {
    str1Length = str1.split(".")[1].length
  } catch (error) {
    str1Length = 0
  }
  try {
    str2Length = str2.split(".")[1].length
  } catch (error) {
    str2Length = 0
  }

  var step = 10 ** Math.max(str1Length, str2Length)
  switch (symbol) {
    case "+":
      result = (num1 * step + num2 * step) / step
      break
    case "-":
      result = (num1 * step - num2 * step) / step
      break
    case "*":
      result = (num1 * step * (num2 * step)) / step / step
      break
    case "/":
      if (num1 == 0) {
        result = 0
      } else {
        result = (num1 * step) / (num2 * step)
      }
      break
    default:
      break
  }
  if (fixLen) {
    return result.toFixed(fixLen)
  }
  return result
}
/**将对象的值封装成数组 */
export const objetToArr = (obj: anyObj) => {
  return Object.keys(obj).map((key) => obj[key])
}

/**
 * 设置层级偏移
 * @param value  数值
 * @param level  层级
 * @returns
 */
export function SetCenter(value: any, level: any) {
  if (value) {
    if (value.indexOf("合") == 0 && value.indexOf("计") == value.length - 1) {
      return (
        <div
          style={{ textAlign: "center" }}
          dangerouslySetInnerHTML={{
            __html: replace_spacetonbsp(value),
          }}></div>
      )
    } else {
      if (value.indexOf(" ") == 0) {
        return (
          <span
            style={{ color: "#808080" }}
            dangerouslySetInnerHTML={{
              __html: replace_spacetonbsp(value),
            }}></span>
        )
      } else if (level && level > 0) {
        var prev = ""
        for (var i = 0; i < level; i++) {
          prev += "    "
        }
        return (
          <span
            style={{ color: "#808080" }}
            dangerouslySetInnerHTML={{
              __html: replace_spacetonbsp(prev + value),
            }}></span>
        )
      } else {
        return value
      }
    }
  } else {
    return ""
  }
}

export const replace_spacetonbsp = (value: any) => {
  var result = value.replace(/ /g, "&nbsp")
  return result
}

/** 分组排序 */
export function groupByList(arr: any, name: any) {
  const groups: any = {}
  arr.forEach(function (f: any) {
    const group: any = JSON.stringify(f[name])
    groups[group] = groups[group] || []
    groups[group].push(f)
  })
  return Object.keys(groups).map(function (group) {
    return groups[group]
  })
}

/**
 * 获取合同基本单位/人员信息
 * @param list 获取的人员list
 * @param type 类型 1查人 2查单位 3 查单位负责人
 * @param lx 当前类型
 * @returns
 */
export function getPeoUnitString(list: any, type: number, lx?: string) {
  switch (type) {
    case 1:
      if (list?.users?.length > 0)
        return list?.users
          ?.filter((item: any) => item.rylx == lx)
          .map((item: any) => item.mc + " " + item.lxdh)
          ?.join(",")
    case 2:
      if (list?.units?.length > 0)
        return list.units
          ?.filter((item: any) => item.dwlxmc == lx)
          .map((item: any) => item.dwmc)
          ?.join(",")
    case 3:
      if (list?.units?.length > 0) {
        let people: any[] = []
        list.units?.forEach((item: any) => {
          if (item.fzr) {
            people.push(item?.fzr?.mc)
          }
        })
        return people.join(",")
      }
  }
  return ""
}
/**将数组对象里具有相同值的组合成数组 */
export const IdenticalValueArr = (arr: any[], str: string) => {
  let grouping = arr.reduce((acc, obj) => {
    const key = obj[str]
    if (!acc.has(key)) acc.set(key, [])
    acc.get(key).push(obj)
    return acc
  }, new Map())

  let groupsArray = Array.from(grouping.values())
  return groupsArray
}

// 防连点(2s内触发一次)
export const debounce = (
  func: any,
  wait: number = 2000,
  options: DebounceSettings = {}
) => {
  return _.debounce(func, wait, {
    leading: true,
    trailing: false,
    ...options,
  })
}

/**
 * 解决两个数相乘精度丢失问题
 * @param a
 * @param b
 * @returns {Number}
 */
export const floatMul = (a: number | string, b: number | string) => {
  if (a === undefined || a === null || b === undefined || b === null) return a
  let c = 0,
    d = a.toString(),
    e = b.toString()
  try {
    c += d.split(".")[1].length
  } catch (f) { }
  try {
    c += e.split(".")[1].length
  } catch (f) { }
  return (
    (Number(d.replace(".", "")) * Number(e.replace(".", ""))) / Math.pow(10, c)
  )
}

/**
 * 获取指定年份到现在年份
 * @param val 指定年份
 * @returns
 */
export const getYear = (val: any) => {
  // 获取指定年份开始到现在年份的数组
  //获取到从那一年开始
  let timList: any[] = []
  let smallYears = val

  let date = new Date() //获取当前时间
  let NowYears = date.getFullYear()
  var Years = NowYears - smallYears
  let arrTim = []
  for (let index = 0; index <= Years; index++) {
    arrTim.push(NowYears--)
  }
  arrTim.forEach((tim) => {
    timList.push(tim)
  })
  return timList
}

/**
 * 获取数组层级
 * @param arr 
 */
export const getArrLevel = (arr: any[], childrenFieldName: string = "children") => {
  let i = 1
  const v = (list: any[], level: number = 1) => {
    list.forEach((item: any) => {
      if (item[childrenFieldName]?.length) {
        if (level = i) i++
        v(item[childrenFieldName], level + 1)
      }
    })
  }
  v(arr)
  return i
}

/** state、ref 同时使用 防止拿不到最新值 */
export const useRefState = <S,>(
  p: S
): [S, Dispatch<SetStateAction<S>>, MutableRefObject<S>] => {
  const [state, setState] = useState(p);
  const ref = useRef(state);
  ref.current = state;
  return [
    state,
    (newVal) => {
      setState(newVal);
      ref.current = isFunction(newVal) ? newVal(state) : newVal;
    },
    ref,
  ];
};
